package com.zzk.rxmvvmbase.base;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;

import androidx.annotation.NonNull;

import com.blankj.utilcode.util.CrashUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ProcessUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.zzk.rxmvvmbase.utils.Utils;

import java.util.ArrayList;

import me.jessyan.autosize.AutoSizeConfig;

/**
 * @ProjectName: RXMVVMBase
 * @Package: com.zzk.rxmvvmbase
 * @ClassName:
 * @Description:
 * @Author: brilliantzhao
 * @CreateDate: 2021.1.13 10:12
 * @UpdateUser:
 * @UpdateDate: 2021.1.13 10:12
 * @UpdateRemark:
 * @Version: 1.0.0
 */
public class BaseApplication extends Application {

    //##########################  custom variables start ##########################################

    private final String TAG = getClass().getSimpleName();
    //
    private static BaseApplication sInstance;
    public Context context;

    // 是否是主线程，解决多线程重复初始化问题
    private Boolean isMainProcess;

    //##########################  custom variables end  ###########################################

    //##########################  override custom metohds start ###################################

    /**
     * 程序创建的时候执行
     * 这个函数是当应用开始之时就被调用了，比其他对象创建的早，这个实现要尽可能的快一点，因为创建时间直接在进程中
     * 影响到我们第一个activity/service或者receiver。如果你要重写这个方法必须调用super.onCreate()。
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
        isMainProcess = isMainProcess();
        // 获取去全局context
        context = getApplicationContext();
        //
        setApplication(BaseApplication.this);
        //=== init AndroidUtilCode
        // init it in the function of onCreate in ur Application
        Utils.init(this);
        //
        initUtilCodeXCrash();
        // AutoSize开启支持 Fragment 自定义参数的功能
        AutoSizeConfig.getInstance().setCustomFragment(true);
    }

    /**
     * 程序终止的时候执行
     * 当终止应用程序对象时调用，不保证一定被调用，当程序是被内核终止以便为其他应用程序释放资源，那
     * 么将不会提醒，并且不调用应用程序的对象的onTerminate方法而直接终止进程
     */
    @Override
    public void onTerminate() {
        super.onTerminate();
        Log.i(TAG, "onTerminate");
    }

    /**
     * 当后台程序已经终止资源还匮乏时会调用这个方法。好的应用程序一般会在这个方法里面释放一些不必
     * 要的资源来应付当后台程序已经终止，前台应用程序内存还不够时的情况。
     */
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        Log.i(TAG, "onLowMemory");
    }

    /**
     * 程序在内存清理的时候执行
     * HOME键退出应用程序、长按MENU键，打开Recent TASK都会执行
     *
     * @param level
     */
    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        Log.i(TAG, "onTrimMemory");
    }

    /**
     * 配置改变时触发这个方法
     *
     * @param newConfig
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        Log.i(TAG, "onConfigurationChanged");
    }

    //##########################  override custom metohds end  ####################################

    //##########################  override third methods start ####################################

    //##########################  override third methods end  #####################################

    //##########################  custom metohds start     ########################################

    /**
     * 当主工程没有继承BaseApplication时，可以使用setApplication方法初始化BaseApplication
     *
     * @param application
     */
    public static synchronized BaseApplication setApplication(@NonNull BaseApplication application) {
        // 实例个人Application类
        sInstance = application;
        // 初始化工具类，传入applicatin,方便全局使用
        Utils.init(application);
        // 注册监听每个activity的生命周期,便于堆栈式管理
        application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                AppManager.getAppManager().addActivity(activity);
            }

            @Override
            public void onActivityStarted(Activity activity) {
            }

            @Override
            public void onActivityResumed(Activity activity) {
            }

            @Override
            public void onActivityPaused(Activity activity) {
            }

            @Override
            public void onActivityStopped(Activity activity) {
            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
                AppManager.getAppManager().removeActivity(activity);
            }
        });
        return sInstance;
    }

    /**
     * 获得当前app运行的Application
     */
    public static BaseApplication getInstance() {
        if (sInstance == null) {
            synchronized (BaseApplication.class) {
                if (sInstance == null) {
                    sInstance = setApplication(new BaseApplication());
                }
            }
        }
        return sInstance;
    }


    /**
     * init it in ur application
     *
     * @param isShowLog
     */
    public void initUtilCodeXLog(boolean isShowLog) {
        LogUtils.Config config = LogUtils.getConfig()
                .setLogSwitch(isShowLog)// 设置 log 总开关，包括输出到控制台和文件，默认开
                .setConsoleSwitch(isShowLog)// 设置是否输出到控制台开关，默认开
                .setGlobalTag(null)// 设置 log 全局标签，默认为空
                // 当全局标签不为空时，我们输出的 log 全部为该 tag，
                // 为空时，如果传入的 tag 为空那就显示类名，否则显示 tag
                .setLogHeadSwitch(true)// 设置 log 头信息开关，默认为开
                .setLog2FileSwitch(false)// 打印 log 时是否存到文件的开关，默认关
                .setDir("")// 当自定义路径为空时，写入应用的/cache/log/目录中
                .setFilePrefix("")// 当文件前缀为空时，默认为"util"，即写入文件为"util-yyyy-MM-dd$fileExtension"
                .setFileExtension(".log")// 设置日志文件后缀
                .setBorderSwitch(true)// 输出日志是否带边框开关，默认开
                .setSingleTagSwitch(true)// 一条日志仅输出一条，默认开，为美化 AS 3.1 的 Logcat
                .setConsoleFilter(LogUtils.V)// log 的控制台过滤器，和 logcat 过滤器同理，默认 Verbose
                .setFileFilter(LogUtils.V)// log 文件过滤器，和 logcat 过滤器同理，默认 Verbose
                .setStackDeep(1)// log 栈深度，默认为 1
                .setStackOffset(0)// 设置栈偏移，比如二次封装的话就需要设置，默认为 0
                .setSaveDays(3)// 设置日志可保留天数，默认为 -1 表示无限时长
                // 新增 ArrayList 格式化器，默认已支持 Array, Throwable, Bundle, Intent 的格式化输出
                .addFormatter(new LogUtils.IFormatter<ArrayList>() {
                    @Override
                    public String format(ArrayList arrayList) {
                        return "LogUtils Formatter ArrayList { " + arrayList.toString() + " }";
                    }
                })
                .addFileExtraHead("ExtraKey", "ExtraValue");
        LogUtils.i(config.toString());
        // 改变toast显示位置
        ToastUtils.getDefaultMaker().setGravity(Gravity.CENTER, 0, 0);
    }

    /**
     * utilcodex的crash初始化
     */
    private void initUtilCodeXCrash() {
        CrashUtils.init(new CrashUtils.OnCrashListener() {
            @Override
            public void onCrash(CrashUtils.CrashInfo crashInfo) {
                crashInfo.addExtraHead("extraKey", "extraValue");
                LogUtils.e(crashInfo.toString());
//                AppUtils.relaunchApp();
            }
        });
    }

    /**
     * @return
     */
    private boolean isMainProcess() {
        return ProcessUtils.isMainProcess();
    }

    //##########################  custom metohds end   ############################################

}
